package zunge.twidel.typo;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

import zunge.tool.text.StringDistance;

public class TypoCheck {
	
	public static final int TYPE_NORMAL = 0;
	public static final int TYPE_TYPO = 1;
	public static final int TYPE_REPOST = 2;
	
	public int T = 4;		//Threshold for edit distance
	public double R = 0.6;	//Threshold for cosine similarity
	public int LEN = 10;	//Minimal tweet length to calculate edit distance
	public int L = 8;		//Minimal tokens to calculate cosine similarity
	
	public TypoCheck(int T, double R, int LEN, int L){
		this.T = T;
		this.R = R;
		this.LEN = LEN;
		this.L = L;
	}
	
	/**
	 * Get type(Normal/Typo/Repost) of a tweet, comparing to some previous tweet.
	 * 
	 * @param curr
	 * @param prev
	 * @return
	 */
	public int typoCheck(String curr, String prev){
		if(curr == null || prev == null){
			return -1;
		}
		
		String cur = TweetCleaner.remove(curr);
		String pre = TweetCleaner.remove(prev);
		if(cur!=null && pre!=null && cur.equals(pre)){
			return TYPE_REPOST;
		}
		
		//cur = TweetCleaner.abReorder(cur);
		//pre = TweetCleaner.abReorder(pre);
		//if(cur!=null && pre!=null && cur.equals(pre)){
		//	return TYPE_REPOST;
		//}
		
		cur = TweetCleaner.replace(curr);
		pre = TweetCleaner.replace(prev);
		if(EditDistance(cur, pre) <= T){
			return TYPE_TYPO;
		}
		else if(CosineSimilarity(cur,pre) >= R){
			return TYPE_REPOST;
		}
		
		
		return TYPE_NORMAL;
		
		/*
		 * label  getProperty(tweet1, tweet2)
        <1>    Remove all "#tag",  remove all "@username", replace all URLs using "URL", 
                  if tweet1 == tweet2, return REPOST
        <2>    Tokenize,  reorder the tokens subject to alphabets, 
                  if tweet1 == tweet2,  return REPOST
        <3>    Remove all "#",  replace all "@username" using "USER", replace all URLs using "URL",  
                  If edit distance (tweet1, tweet2)  <= T ,  return TYPO
        		  If cosine similarity(tweet1, tweet2) >= R,  return REPOST
		 */
	}
	
	public int EditDistance(String tweet1, String tweet2){
		if(tweet1.length()<LEN || tweet2.length() < LEN){return Integer.MAX_VALUE;}
		
		int dist = StringDistance.distance(tweet1, tweet2);
		
		//if(dist == T+1){System.out.println("FE "+tweet1+"########"+tweet2);}
		
		return dist;
	}
	
	public double CosineSimilarity(String tweet1, String tweet2){
		List<String> t1 = TweetCleaner.tokenize(tweet1);
		List<String> t2 = TweetCleaner.tokenize(tweet2);
	
		if(t1.size() < L || t2.size() < L){return 0;}
		
		HashMap<String,Integer> dict = new HashMap<String,Integer>();
		for(String s:t1){if(!dict.containsKey(s)){dict.put(s, dict.size());}}
		for(String s:t2){if(!dict.containsKey(s)){dict.put(s, dict.size());}}
		
		int[] v1 = new int[dict.size()];
		int[] v2 = new int[dict.size()];
		Arrays.fill(v1, 0);
		Arrays.fill(v2, 0);
		for(String s:t1){v1[dict.get(s)]=1;}
		for(String s:t2){v2[dict.get(s)]=1;}
		
		double inner = 0;
		double s1 = 0;
		double s2 = 0;
		for(int i = 0;i < dict.size();++i){
			inner += v1[i]*v2[i];
			s1 += v1[i]*v1[i];
			s2 += v2[i]*v2[i];
		}
		
		double cos = inner/(Math.sqrt(s1)*Math.sqrt(s2));
		
		//if(cos > R){}//System.out.println("T "+tweet1+"########"+tweet2);}
		//else if(cos > (R-0.05)){System.out.println("FC "+tweet1+"########"+tweet2);}
		
		return cos;
	}
}
